

#ifndef _SCHEDULER_H_
#define _SCHEDULER_H_


#include "Coroutine.h"
#include "Thread.h"
#include <atomic>
#include <cstddef>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/epoll.h>
#include <iostream>


namespace zepco {

class Scheduler {
  public:
    /**
     * @brief Construct a new Scheduler object
     *
     * @param threads 指定线程的数量
     * @param user_caller 指定是否将主线程作为工作线程
     * @param name 调度器名称
     */
    Scheduler(size_t threads = 1, bool use_caller = true, const std::string &name = "Scheduler");
    virtual ~Scheduler();
    const std::string &getName() const {
        return m_name;
    }

  public:
    static Scheduler *GetThis(); // 获取正在运行的调度器

  protected:
    void SetThis(); // 设置正在运行的调度器

  public:
    /**
     * @brief 添加任务到任务队列
     *
     * @tparam ZephyrOrCallback 调度任务类型
     * @param zc 协程或回调
     * @param thread 指定要运行的线程id
     */
    template<typename ZephyrOrCallback>
    void scheduleLock(ZephyrOrCallback zc, int thread = -1) {
        bool need_tickle;
        {
            std::lock_guard<std::mutex> lock(m_mtx);
            // empty -> all thread is idle -> need to be waken up
            need_tickle = m_task.empty();
            SchedulerTask task(zc, thread);
            if (task.zephyr || task.callback) {
                // std::cout << "push task: thread = " << task.thread << std::endl;
                m_task.push_back(task);
            }
        }
        if (need_tickle) {
            tickle();
        }
    }
    //  启动线程池
    virtual void start();
    // 关闭线程池,停止调度器, 等所有调度任务完成后返回
    virtual void stop();

  protected:
    // 唤醒线程
    virtual void tickle();
    // 线程函数
    virtual void run();
    // 空闲协程函数
    virtual void idle();
    // 是否可以关闭
    virtual bool stopping();

    // 返回是否有空闲线程
    // 当调度协程进入idle时 空闲协程数加一
    // 当调度协程离开idle时 空闲协程数减一
    bool hasIdleThreads() {
        return m_idleThreadCount > 0;
    }

  private:

    struct SchedulerTask {
        std::shared_ptr<Zephyr> zephyr;
        std::function<void()> callback;
        int thread; // 指定任务需要运行的线程id

        SchedulerTask() {
            zephyr = nullptr;
            callback = nullptr;
            thread = -1;
        }

        SchedulerTask(std::shared_ptr<Zephyr> z, int thr) {
            zephyr = z;
            thread = thr;
        }

        // 不增加引用计数
        SchedulerTask(std::shared_ptr<Zephyr> *z, int thr) {
            zephyr.swap(*z); 
            thread = thr;
        }

        SchedulerTask(std::function<void()> f, int thr) {
            callback = f;
            thread = thr;
        }

        // 不增加引用计数
        SchedulerTask(std::function<void()> *f, int thr) {
            callback.swap(*f);
            thread = thr;
        }

        void reset() {
            zephyr = nullptr;
            callback = nullptr;
            thread = -1;
        }
    };

    std::string m_name; // 调度器名称
    std::mutex m_mtx; // 保护任务队列
    std::vector<std::shared_ptr<Thread>> m_threads; // 线程池
    std::vector<SchedulerTask> m_task; // 任务对列
    std::vector<int> m_threadIds; // 存储工作线程的id
    size_t m_threadCount = 0; // 需要额外创建的线程数
    std::atomic<size_t> m_activateThreadCount{0}; // 活跃线程数
    std::atomic<size_t> m_idleThreadCount{0}; // 空闲线程数
    bool m_userCaller; // 主线程是否用作工作线程
    std::shared_ptr<Zephyr> m_schedulerZephyr; // 如果是 ->需要额外创建调度协程
    int m_rootThread = -1; // 如果是 -> 记录主线程的id
    bool m_stoping = false; // 是否正在关闭
};



}

#endif // _SCHEDULER_H_